package com.helloandroid.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat.getColor
import com.helloandroid.AppUtil
import com.helloandroid.R
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.sin

class DashBoard @JvmOverloads constructor(
        ctx: Context,
        attrs: AttributeSet? = null,
        defStyle: Int = 0
) : View(ctx, attrs, defStyle) {

    companion object {
        const val DCount = 40 // 分成40分
        const val DegressPiece = 180.0f / DCount
        const val DefaultBgColor = Color.GRAY
        const val DefaultFgColor = Color.BLUE
    }

    var pointArr = FloatArray((DCount + 1) * 4)

    private val minTextOffset = PointF()
    private val midTextOffset = PointF()
    private val maxTextOffset = PointF()
    val center = PointF()

    // paint
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val linePaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private val rect = RectF()

    private var maxNum = 6000 // 默认为6000
    private var curNum = 0

    //========================================
    // fields
    private val bgColor: Int
    private val fgColor: Int
    private val bigR: Float
    var r1 = 0f  // 表示从左到右  刻度直线的起点位置  所在半径
    var r2 = 0f  // 表示 小刻度直线的终点位置 所在的半径
    var r3 = 0f  // 表示 大刻度直线的终点位置 所在的半径

    init {
        val typedArray = ctx.obtainStyledAttributes(attrs, R.styleable.DashBoard)
        bgColor = typedArray.getColor(R.styleable.DashBoard_bg_color, DefaultBgColor)
        fgColor = typedArray.getColor(R.styleable.DashBoard_fg_color, DefaultFgColor)
        bigR = typedArray.getDimension(R.styleable.DashBoard_big_r, resources.getDimension(R.dimen.dp113))
        typedArray.recycle()
        init()
    }

    private fun init() {

        r1 = bigR - resources.getDimension(R.dimen.dp8)
        r2 = r1 - resources.getDimension(R.dimen.dp3)
        r3 = r2 - resources.getDimension(R.dimen.dp3)

        // 设置 paint
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = resources.getDimension(R.dimen.dp8)
        paint.strokeCap = Paint.Cap.ROUND

        linePaint.style = Paint.Style.FILL
        linePaint.color = bgColor
        linePaint.strokeWidth = resources.getDimension(R.dimen.dp1)

        textPaint.color = getColor(context, R.color.dd_main_blue)
        textPaint.textSize = resources.getDimension(R.dimen.sp10)

        minTextOffset.set(resources.getDimension(R.dimen.dp2), resources.getDimension(R.dimen.dp3))
        midTextOffset.set(0f, resources.getDimension(R.dimen.dp9))
        maxTextOffset.set(-resources.getDimension(R.dimen.dp2), resources.getDimension(R.dimen.dp3))
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)

        var newWidth = widthSize
        var newHeight = heightSize

        // width
        if (widthMode == MeasureSpec.EXACTLY) {
            newWidth = widthSize
        } else {
            newWidth = widthSize
            if (widthMode == MeasureSpec.AT_MOST) {
                newWidth = min(newWidth, AppUtil.dm.widthPixels)
            }
        }

        // height
        if (heightMode == MeasureSpec.EXACTLY) {
            newHeight = heightSize
        } else {
            newHeight = heightSize
            if (heightMode == MeasureSpec.AT_MOST) {
                newHeight = min(newHeight, resources.getDimension(R.dimen.dp220).toInt())
            }
        }
        setMeasuredDimension(newWidth, newHeight)
    }

    override fun onDraw(pcanvas: Canvas?) {
        super.onDraw(pcanvas)

        val canvas = pcanvas!!

        // 先确定半径 和  圆心
        center.y = (height - bigR) / 2.0f + bigR
        center.x = width / 2.0f
        rect.left = (width - 2 * bigR) / 2.0f
        rect.right = width - rect.left
        rect.top = center.y - bigR
        rect.bottom = rect.top + 2 * bigR

        // 1.先绘制背景
        paint.color = bgColor
        canvas.drawArc(rect, 180f, 180f, false, paint)

        canvas.save()
        canvas.translate(center.x, center.y)

        var x: Float
        var y: Float
        var x1: Float
        var y1: Float
        for (i in 0..DCount) {
            val deg = DegressPiece * i
            val rad = Math.toRadians((deg + 180).toDouble())
            val sin = sin(rad)
            val cos = cos(rad)
            x = (cos * r1).toFloat()
            y = (sin * r1).toFloat()
            if (i % 10 == 0) {
                x1 = (cos * r3).toFloat()
                y1 = (sin * r3).toFloat()
            } else {
                x1 = (cos * r2).toFloat()
                y1 = (sin * r2).toFloat()
            }
            pointArr[4 * i] = x
            pointArr[4 * i + 1] = y;
            pointArr[4 * i + 2] = x1
            pointArr[4 * i + 3] = y1;
        }
        canvas.drawLines(pointArr, linePaint)

        // 绘制数字
        textPaint.textAlign = Paint.Align.LEFT
        canvas.drawText("0", -r3 + minTextOffset.x, 0 + minTextOffset.y, textPaint)

        textPaint.textAlign = Paint.Align.CENTER
        canvas.drawText((maxNum / 2).toString(), 0 + midTextOffset.x, -r3 + midTextOffset.y, textPaint)

        textPaint.textAlign = Paint.Align.RIGHT
        canvas.drawText(maxNum.toString(), r3 + maxTextOffset.x, 0 + maxTextOffset.y, textPaint)
        canvas.restore()

        // 绘制前面
        paint.color = fgColor

        var progress = curNum.toFloat() / maxNum.toFloat()
        if (progress > 1.0f) {
            progress = 1.0f
        }
        val finalDeg = progress * 180
        canvas.drawArc(rect, 180f, finalDeg, false, paint)
    }

    fun setMaxNum(max: Int) {
        maxNum = max
    }

    fun updateProgress(curValue: Int) {
        curNum = curValue
        invalidate()
    }

    fun anim() {
        val animator = ValueAnimator.ofInt(0, maxNum, curNum)
        animator.duration = 2500L
        animator.addUpdateListener {
            val curValue = it.animatedValue
            updateProgress(curValue as Int)
        }
        animator.start()
    }
}